<template>
  <div class="main">
    <div id="cesiumContainer"></div>
  </div>
</template>

<script>
var Cesium = require("cesium/Cesium");
import "../../../node_modules/cesium/Source/Widgets/widgets.css";
import $ from "jquery"
export default {
  name:"Map",
  data() {
    return {
      viewer: "",
      position: "",
      center: "",
      reBbox : {//大余县外接矩形的Bbox
        minx: 114.00029582000024,
        miny: 25.256412020000132,
        maxx: 114.68747202800001,
        maxy: 25.623771009999994,
      },
      juxBbox : [],//外接矩形拆分出来的每个小网格的Bbox以及编号
      extend:{},//屏幕可视范围的东西南北
      length:"",//切分出来的每个小网格的高
      cameraHeight: "", //相机的高度
      width:"",//切分出来的每个小网格的宽
      array:[],//存放编号及实体对象的id
      removeKey:[]
    };
  },
  mounted() {
    var that = this;
    Cesium.Ion.defaultAccessToken =
      "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI4MTFmZTI3MC1hZTE0LTRmYzctYTIwMy1lMjQ1ZjgxMGRhM2UiLCJpZCI6NzI4ODQsImlhdCI6MTYzNjQ0MjcyNH0.i6q-HiknfKeuLMD-rMBZ751jBnSCzqC0nHtDpZkaBu0";
      // WebMapServiceImageryProvider
      // ArcGisMapServerImageryProvider
    let maplayer = new Cesium.ArcGisMapServerImageryProvider({
      url: "https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer",
      
    });
    this.viewer = new Cesium.Viewer("cesiumContainer", {
      animation: false, //是否显示动画插件
      shouldAnimation: false, //是否自动显示动画（下方时间轴是不是在走着）
      homeButton: false, //是否显示home按钮
      fullscreenButton: false, // 是否显示全屏按钮
      baseLayerPicker: false, // 是否显示图层选择控件
      geocoder: false, // 是否显示地名查找控件
      timeline: false, // 是否显示时间线控件
      sceneModePicker: false, // 是否显示投影方式控件（右上角的小圆球）
      navigationHelpButton: false, // 是否显示帮助信息控件
      infoBox: false, // 是否显示点击要素之后显示的信息
      sceneMode: 3, // 初始场景模式 1 2D模式 2 2D循环模式 3 3D模式  Cesium.SceneMode
      selectionIndicator: false, //选中指示框
      navigationInstructionsInitiallyVisible: false, // 帮助按钮，初始化的时候是否展开
      mapProjection: new Cesium.WebMercatorProjection(), //地图投影体系
      terrainProvider: Cesium.createWorldTerrain(), //地形图层提供者，仅baseLayerPicker设为false有意义
      contextOptions: {
        webgl: {
          alpha: true,
          depth: true,
          stencil: true,
          antialias: true,
          premultipliedAlpha: true,
          //通过canvas.toDataURL()实现截图需要将该项设置为true
          preserveDrawingBuffer: true,
          failIfMajorPerformanceCaveat: true,
        },
      },
    });
    this.viewer.scene.imageryLayers.addImageryProvider(maplayer); //去除谷歌请求
    // this.viewer.imageryLayers.addImageryProvider(annLayer); //图层类型的添加
    this.viewer.imageryLayers.get(0).show = true; //添加图层
    this.viewer._cesiumWidget._creditContainer.style.display = "none"; // 去除版权信息
    // this.viewer.scene.globe.depthTestAgainstTerrain = true; //地形遮挡(深度监测)
    this.viewer.scene.globe.enableLighting = false; //是否使用地球光照
    this.viewer.scene.globe.showGroundAtmosphere = false; //绘制在地球上的地面大气。
    this.viewer.terrainProvider = Cesium.createWorldTerrain({
      //启用地形照明和水体效果
      requestWaterMask: true,
      requestVertexNormals: true,
    });
    this.viewer.camera.flyTo({
      destination: Cesium.Cartesian3.fromDegrees(114.352497, 25.401622, 1500),
      orientation: {
        heading: Cesium.Math.toRadians(0.0),
        pitch: Cesium.Math.toRadians(-90.0),
        roll: Cesium.Math.toRadians(0.0),
      },
      duration: 5, //飞行时间value
    });
    this.addListener();
    // 将大余县外接矩形x,y,方向各切分500次，并给切分得到的每个小网格赋予相应的编号
    this.length = (that.reBbox.maxy - that.reBbox.miny) / 500;//每个小网格的高
    this.width = (that.reBbox.maxx - that.reBbox.minx) / 500;//每个小网格的宽
    var p = 0
    for (var i = 0; i < 500; i++) {//获取每个网格的Bbox并储存
      let scminy = that.reBbox.maxy - (i + 1) * this.length;
      var scmaxy = that.reBbox.maxy - i * this.length;
      for (var j = 0; j < 500; j++) {
        var obje = {};
        let scminx = that.reBbox.minx + j * this.width;
        let scmaxx = that.reBbox.minx + (j + 1) * this.width;
        obje.minx = scminx;
        obje.maxx = scmaxx;
        obje.miny = scminy;
        obje.maxy = scmaxy;
        if(i<10){
          var a = "00"+i
        }
        else if(i>=10&&i<100){
          var a = "0"+i
        }
        else if(i>=100){
          var a = i
        }
        if(j<10){
          var b = "00"+j
        }
        else if(j>=10&&j<100){
          var b = "0" + j
        }
        else{
          var b = j
        }
        obje.key = a+""+b
        this.juxBbox[p] = obje;
        p++;
      }
    }
  },
  methods: {
    addListener() {
      var dataMap = new Map()
      var that = this
      var bl=0//记录移动的次数
      // that.viewer.camera.changed.addEventListener(function(){//监听相机移动
      // this.viewer.scene.postRender.addEventListener(function(){//实时监听地图
      that.viewer.scene.camera.moveEnd.addEventListener(function(){//相机移动结束开始加载
        let remove = []//当前可视范围内所有网格的编号
        that.cameraHeight = that.viewer.camera.positionCartographic.height
        console.log(that.cameraHeight)
        if(that.cameraHeight<3000){
          // 获取可视范围
          var rectangle = {};
          that.extend = that.viewer.camera.computeViewRectangle(); //可视范围
          rectangle.minx = Cesium.Math.toDegrees(that.extend.west);
          rectangle.miny = Cesium.Math.toDegrees(that.extend.south);
          rectangle.maxx = Cesium.Math.toDegrees(that.extend.east);
          rectangle.maxy = Cesium.Math.toDegrees(that.extend.north);

          // 判断屏幕范围左上角的点在外接矩形中网格的位置
          let dxl = that.juxBbox[0].minx - rectangle.minx//外接矩形的minx到可视范围的minx的距离
          let dyl = that.juxBbox[0].maxy - rectangle.maxy//外接矩形的maxy到可视范围的maxy的距离
          var dixl = ""//可视范围的左上角所在的网格处于外接矩形横向的第几个网格
          var diyl = ""//可视范围的左上角所在的网格处于外接矩形纵向的第几个网格
          
          // 判断屏幕可视范围在外接矩形中的位置
          for(var r=0;r<500;r++){//x方向
            if(that.width * r==Math.abs(dxl)){//屏幕可视范围的点刚好在外接矩形的点上
              // console.log("在横向的第"+r+"个点上")
              dixl = r
            }
            else if(that.width *r<Math.abs(dxl)&&that.width *(r+1)>Math.abs(dxl)){//屏幕的可视范围在外接矩形的小盒子的内部(没在点上)
              // r:在横向的第几个盒子内
              // console.log("在横向的第"+r+"与"+(r+1)+"的盒子内")
              dixl = r
              // return r
            }
          }
          for(var s=0;s<500;s++){//y方向
            if(that.length*s==dyl){//屏幕可视范围的点刚好在外接矩形的点上
              // console.log("在竖向的第"+s+"个点上")
              diyl = s
              // return s//s:在竖向的第几个点上
            }
            else if(that.length*s<dyl&&that.length*(s+1)>dyl){
              //屏幕的可视范围在外接矩形的小盒子的内部(没在点上)
              // s:在竖向的第几个盒子内
              diyl = s
              // console.log("在竖向的第"+s+"与"+(s+1)+"的盒子内")
            }
          }
          // console.log("可视的左上角网格的位置在横向的第"+dixl+"竖向的第"+diyl)

          // 判断屏幕范围右上角的点在外接矩形中网格的位置
          let dxr = that.juxBbox[0].maxx - rectangle.maxx//外接矩形的maxx到可视范围的maxx的距离
          var dixr = ""//可视范围的右上角所在的网格处于外接矩形横向的第几个网格
          
          // 判断屏幕可视范围在外接矩形中的位置
          for(var r=0;r<500;r++){//x方向
            if(that.width * r==Math.abs(dxr)){//屏幕可视范围的点刚好在外接矩形的点上
              // console.log("在横向的第"+r+"个点上")
              dixr = r
            }
            else if(that.width *r<Math.abs(dxr)&&that.width *(r+1)>Math.abs(dxr)){//屏幕的可视范围在外接矩形的小盒子的内部(没在点上)
              // r:在横向的第几个盒子内
              // console.log("在横向的第"+r+"与"+(r+1)+"的盒子内")
              dixr = r
              // return r
            }
          }
          // console.log("可视的右上角的网格的位置在横向的第"+dixr+"竖向的第"+diyl)

          // 判断屏幕范围左下角的点在外接矩形中网格的位置
          let dylb = that.juxBbox[0].miny - rectangle.miny//外接矩形的miny到可视范围的miny的距离
          var diylb = ""//可视范围的左下角所在的网格处于外接矩形纵向的第几个网格
          // 判断屏幕可视范围在外接矩形中的位置
          for(var s=0;s<500;s++){//y方向
            if(that.length*s==dylb){//屏幕可视范围的点刚好在外接矩形的点上
              // console.log("在竖向的第"+s+"个点上")
              diylb = s
              // return s//s:在竖向的第几个点上
            }
            else if(that.length*s<dylb&&that.length*(s+1)>dylb){
              //屏幕的可视范围在外接矩形的小盒子的内部(没在点上)
              // s:在竖向的第几个盒子内
              diylb = s
              // console.log("在竖向的第"+s+"与"+(s+1)+"的盒子内")
            }
          }
          // console.log("可视的左下角的网格的位置在横向的第"+dixl+"竖向的第"+diylb)
          // dixl、dixr(左、右)
          // diyl、diylb(上、下)
          // 屏幕范围右下角的点在外接矩形中网格的位置
          // console.log("可视的右下角的网格的位置在横向的第"+dixr+"竖向的第"+diylb)
          // 网格的位置在数组中的下标为：纵向*500+横向
          // 左上角所在网格在数组中的下标：
          var wblt = diyl * 500 + dixl
          // console.log(that.juxBbox[wblt])
          var wbrt = diyl * 500 + dixr
          //右下角所在网格在数组中的下标：
          var wbrb = diylb * 500 +  dixr
          // 左下角所在网格在数组中的下标：
          var wblb = diylb * 500 + dixl
          // console.log(that.juxBbox[wbrb])
          // console.log(wbrb)
          var url2 = "http://112.94.21.83:25015/geoserver/cite/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=cite%3Adayu_building_merge1&outputFormat=application%2Fjson";
          if(bl==0){//第一次进来没有移动时加载
            for(var k=wblt;k<=wbrt+1;k++){//从左到右
              for(var j=k;j<=wbrb+500;j=j+500){//由上到下
                var bbox2 = that.juxBbox[j].minx+","+that.juxBbox[j].miny+","+that.juxBbox[j].maxx+","+that.juxBbox[j].maxy
                // console.log(that.juxBbox[j])
                let object = {}
                let id = []
                // axios.get(url2, {params: {bbox: bbox2,},}).then((res) =>{})
                $.ajax({
                  url:url2,
                  data:{
                    bbox:bbox2
                  },
                  async:false,//设置请求为同步请求
                  type:"get",
                  success:function(res){
                    // console.log(res)
                    var datasource2 = Cesium.GeoJsonDataSource.load(res);
                    datasource2.then(function(source){
                      if(that.viewer.dataSources._dataSources.length>0){//去重
                        // console.log(that.juxBbox[j].key)
                        // // 与that.juxBbox[j-1]对比判断
                        for(var s=0;s<that.array.length;s++){//与that.juxBbox[j-1]对比判断
                          if(that.juxBbox[j-1].key==that.array[s].name){//在array数组中找到前一个已经加载的网格的信息
                            for(var e=0;e<that.array[s].arrayId.length;e++){//循环拿到上一个加载所有实体的id
                              for(var d=0;d<source.entities.values.length;d++){//循环拿到当前获取过来的所有实体的id
                                if(source.entities.values[d]._id==that.array[s].arrayId[e]){//判断如果有重复的，则删除重复
                                  source.entities.values.splice(d,1)
                                  d = d-1
                                }
                              }
                            }
                          }
                        }
                        if(that.juxBbox[j-499]){//与that.juxBbox[j-499]对比判断
                          for(var s2=0;s2<that.array.length;s2++){
                            if(that.juxBbox[j-499].key==that.array[s2].name){
                              for(var e2=0;e2<that.array[s2].arrayId.length;e2++){
                                for(var d2=0;d2<source.entities.values.length;d2++){
                                  if(source.entities.values[d2]._id==that.array[s2].arrayId[e2]){
                                    source.entities.values.splice(d2,1)
                                    d2 = d2 - 1
                                  }
                                }
                              }
                            }
                          }
                        }
                        if(that.juxBbox[j-500]){//与that.juxBbox[j-500]对比判断
                        // console.log("执行")
                          for(var s3=0;s3<that.array.length;s3++){
                            if(that.juxBbox[j-500].key==that.array[s3].name){
                              for(var e3=0;e3<that.array[s3].arrayId.length;e3++){
                                for(var d3=0;d3<source.entities.values.length;d3++){
                                  if(source.entities.values[d3]._id==that.array[s3].arrayId[e3]){
                                    source.entities.values.splice(d3,1)
                                    d3 = d3 - 1
                                  }
                                }
                              }
                            }
                          }
                        }
                        if(that.juxBbox[j-501]){//与that.juxBbox[j-501]对比判断
                          for(var s4=0;s4<that.array.length;s4++){
                            if(that.juxBbox[j-501].key==that.array[s4].name){
                              for(var e4=0;e4<that.array[s4].arrayId.length;e4++){
                                for(var d4=0;d4<source.entities.values.length;d4++){
                                  if(source.entities.values[d4]._id==that.array[s4].arrayId[e4]){
                                    source.entities.values.splice(d4,1)
                                    d4 = d4 - 1
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                      // 实体对象的id：source.entities.values[c]._id
                      for(var c=0;c<source.entities.values.length;c++){
                        id.push(source.entities.values[c]._id)
                      }
                      object.arrayId = id
                      source._name = that.juxBbox[j].key
                      that.viewer.dataSources.add(source)
                    })
                  }
                })
                object.name = that.juxBbox[j].key
                that.removeKey.push(object.name)
                that.array.push(object)
                dataMap.set(object.name,object.arrayId)
                remove.push(that.juxBbox[j].key)
              }
            }
          }
          else{//移动了
          // console.log(wblt - that.wblt1)
          // 加载
            for(var k1=wblt;k1<=wbrt+1;k1++){
              for(var j1=k1;j1<=wbrb+500;j1=j1+500){//得到当前可视范围内网格编号
                remove.push(that.juxBbox[j1].key)//将得到的当前可视网格的编号赋值给remove
                  if(that.removeKey.indexOf(that.juxBbox[j1].key)==-1){//当前的网格没加载过
                    var bbox3 = that.juxBbox[j1].minx+","+that.juxBbox[j1].miny+","+that.juxBbox[j1].maxx+","+that.juxBbox[j1].maxy
                    let object2 = {}
                    let id2 = []
                    $.ajax({
                      url:url2,
                      data:{
                        bbox:bbox3
                      },
                      async:false,
                      type:"get",
                      success:function(res){
                        var datasource3 = Cesium.GeoJsonDataSource.load(res);
                        datasource3.then(function(source){
                          // 去重
                          for(var s=0;s<that.array.length;s++){//与that.juxBbox[j-1]对比判断
                            if(that.juxBbox[j1-1].key==that.array[s].name){//在array数组中找到前一个已经加载的网格的信息
                              for(var e=0;e<that.array[s].arrayId.length;e++){//循环拿到上一个加载所有实体的id
                                for(var d=0;d<source.entities.values.length;d++){//循环拿到当前获取过来的所有实体的id
                                  if(source.entities.values[d]._id==that.array[s].arrayId[e]){//判断如果有重复的，则删除重复
                                    source.entities.values.splice(d,1)
                                    d = d - 1
                                  }
                                }
                              }
                            }
                          }
                          if(that.juxBbox[j1-499]){//与that.juxBbox[j-499]对比判断
                            for(var s2=0;s2<that.array.length;s2++){
                              if(that.juxBbox[j1-499].key==that.array[s2].name){
                                for(var e2=0;e2<that.array[s2].arrayId.length;e2++){
                                  for(var d2=0;d2<source.entities.values.length;d2++){
                                    if(source.entities.values[d2]._id==that.array[s2].arrayId[e2]){
                                      source.entities.values.splice(d2,1)
                                      d2 = d2 - 1
                                    }
                                  }
                                }
                              }
                            }
                          }
                          if(that.juxBbox[j1-500]){//与that.juxBbox[j-500]对比判断
                          // console.log("执行")
                            for(var s3=0;s3<that.array.length;s3++){
                              if(that.juxBbox[j1-500].key==that.array[s3].name){
                                for(var e3=0;e3<that.array[s3].arrayId.length;e3++){
                                  for(var d3=0;d3<source.entities.values.length;d3++){
                                    if(source.entities.values[d3]._id==that.array[s3].arrayId[e3]){
                                      source.entities.values.splice(d3,1)
                                      d3 = d3 - 1
                                    }
                                  }
                                }
                              }
                            }
                          }
                          if(that.juxBbox[j1-501]){//与that.juxBbox[j-501]对比判断
                            for(var s4=0;s4<that.array.length;s4++){
                              if(that.juxBbox[j1-501].key==that.array[s4].name){
                                for(var e4=0;e4<that.array[s4].arrayId.length;e4++){
                                  for(var d4=0;d4<source.entities.values.length;d4++){
                                    if(source.entities.values[d4]._id==that.array[s4].arrayId[e4]){
                                      source.entities.values.splice(d4,1)
                                      d4 = d4 - 1
                                    }
                                  }
                                }
                              }
                            }
                          }
                          // 实体对象的id：source.entities.values[c]._id
                          for(var c=0;c<source.entities.values.length;c++){
                            id2.push(source.entities.values[c]._id)
                          }
                          object2.arrayId = id2
                          source._name = that.juxBbox[j1].key
                          that.viewer.dataSources.add(source)
                          // that.viewer.dataSources._dataSources
                          // console.log(source)
                        })
                      }
                    })
                    object2.name = that.juxBbox[j1].key
                    that.array.push(object2)
                    dataMap.set(object2.name,object2.arrayId)
                    that.removeKey.push(object2.name)
                  }
              }
            }
            // 卸载
            var _dataSources = that.viewer.dataSources._dataSources
            for(var a3=0;a3<that.array.length;a3++){
              if(that.array[a3].name){
                // remove：当前可视范围内的加载过的每个网格的编号（移动后）
                // that.array[a3]：已经加载过的所有网格的编号
                // 判断如果that.array[a3]中存在的编号在 remove中不存在则需要卸载
                if(remove.indexOf(that.array[a3].name)==-1){
                  for(var i1=0;i1<_dataSources.length;i1++){
                    // console.log(that.array[a3].name)
                    if(_dataSources[i1]._name==that.array[a3].name){
                      that.viewer.dataSources.remove(_dataSources[i1])
                    }
                  }
                  for(var a4=0;a4<that.removeKey.length;a4++){
                    if(that.removeKey[a4]==that.array[a3].name){
                      that.removeKey.splice(a4,1)//将卸载后的网格的编号从that.removeKey删除，避免卸载后下次移动过来无法加载
                      a4 = a4 - 1
                    }
                  }
                  that.array.splice(a3,1)//将卸载后的网格的编号及对应的实体id从that.array删除
                  a3 = a3-1//删除后数组的长度更新，当前的下标变为a3-1
                }
              }
            }
          }
        }
        // console.log("移动了"+bl+"次")
        bl++
        // console.log(that.juxBbox)
        // console.log(that.array)
        // console.log(dataMap)
        // console.log(remove)
        // console.log(that.viewer.dataSources)
      })
    },
  },
};
</script>

<style>
head {
  height: 0;
  margin: 0;
}
html,
body,
#app,
.main,
#cesiumContainer {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  overflow: hidden;
  font-family: sans-serif;
}
</style>